/*
Copyright (C) 2009 Matthew Perry

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This libary/program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.IO;
using BaseTools.Configuration;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Drawing;
using BaseTools.Configuration.Parsers;
using BaseTools.Helpers;

namespace BaseTools.XS
{
	/// <summary>
	/// XBaseTools settings storage
	/// </summary>
	public class XConf
	{
		private static XSettings xsconf = new XSettings("XConf");
		
		/// <summary>
		/// XSettings used in XConf
		/// </summary>
		public static XSettings XConfSettings
		{
			get
			{
				return xsconf;
			}
		}
		
		/// <summary>
		/// Ensures XConf is present. Call this before doing anything.
		/// </summary>
		public static void EnsureXConf()
		{
			xsconf.EnsureProgramGlobal();
			
			if (xsconf.ProgramImage == null)
			{
				ResourceManager resources = new ResourceManager("BaseTools.Images", Assembly.GetExecutingAssembly());
				Bitmap bitmap = (Bitmap)resources.GetObject("xbasetools");
				
				xsconf.ProgramImage = bitmap;
			}
			
			xsconf.ProgramInfo = new XSInfo("XConf", "Matthew \"Scent Tree\" Perry", "XSettings subset for Configurations",
			                            Assembly.GetExecutingAssembly().Location);
			
			DirectoryInfo di = new DirectoryInfo(xsconf.RelativeTo("software"));
			if (!di.Exists)
				di.Create();
		}
		
		
		
		/// <summary>
		/// Whether the directory exists
		/// </summary>
		/// <param name="filename">the directory name</param>
		/// <returns></returns>
		public static bool DirectoryExists(string filename)
		{
			return new DirectoryInfo(xsconf.RelativeTo(filename)).Exists;
		}
		
		/// <summary>
		/// Whether the file exists
		/// </summary>
		/// <param name="filename">the file name</param>
		/// <returns></returns>
		public static bool FileExists(string filename)
		{
			return new FileInfo(xsconf.RelativeTo(filename)).Exists;
		}
		
		/// <summary>
		/// Ensures the directory exists
		/// </summary>
		/// <param name="dirname">the directory name</param>
		/// <returns>Whether the directory already exists</returns>
		public static bool EnsureDirectory(string dirname)
		{
			DirectoryInfo di = new DirectoryInfo(xsconf.RelativeTo(dirname));
			
			if (di.Exists)
			{
				return true;
			}
			else
			{
				di.Create();
				return false;
			}
		}
		
		/// <summary>
		/// Read the config for a protocol filename
		/// </summary>
		/// <param name="url">The url of the config</param>
		/// <returns></returns>
		public static ConfigList ProtocolRead(string url)
		{
			ProtocolInfo pi = new ProtocolInfo(url);
			return LoadConfig(pi.Path, pi.DefaultConfig);
		}
		
		/// <summary>
		/// Save the config for a protocol filename
		/// </summary>
		/// <param name="url">The url of the config</param>
		/// <param name="lst">The list to write</param>
		/// <returns></returns>
		public static void ProtocolSave(string url, ConfigList lst)
		{
			ProtocolInfo pi = new ProtocolInfo(url);
			SaveConfig(pi.Path, lst, pi.DefaultConfig);
		}
		
		/// <summary>
		/// Load the config for a filename
		/// </summary>
		/// <param name="filename">The filename of the config</param>
		/// <param name="io">The r/w used for the config</param>
		/// <returns></returns>
		public static ConfigList LoadConfig(string filename, IConfig io)
		{
			string xs = xsconf.RelativeTo(filename);
			if (new FileInfo(xs).Exists)
			{
				return io.LoadConfiguration(xs);
			}
			else
			{
				return new ConfigList();
			}
			
		}
		
		/// <summary>
		/// Load the config for a filename
		/// </summary>
		/// <param name="filename">The filename of the config</param>
		/// <returns></returns>
		[Obsolete("Use LoadConfig instead")]
		public static ConfigList ReadConfig(string filename)
		{
			return LoadConfig(filename);
		}
		
		/// <summary>
		/// Load the config for a filename
		/// </summary>
		/// <param name="filename">The filename of the config</param>
		/// <param name="io">The r/w used for the config</param>
		/// <returns></returns>
		[Obsolete("Use LoadConfig instead")]
		public static ConfigList ReadConfig(string filename, IConfig io)
		{
			return LoadConfig(filename, io);
		}
		
		/// <summary>
		/// Load the config for a filename
		/// </summary>
		/// <param name="filename">The filename of the config</param>
		/// <returns></returns>
		public static ConfigList LoadConfig(string filename)
		{
			return LoadConfig(filename, new GeneralConfig());
		}
		
		/// <summary>
		/// Write the config to a file
		/// </summary>
		/// <param name="filename">The file to write to</param>
		/// <param name="lst">The ConfigList to save</param>
		/// <param name="io">The r/w used for the config</param>
		public static void SaveConfig(string filename, ConfigList lst, IConfig io)
		{
			io.SaveConfiguration(xsconf.RelativeTo(filename), lst);
		}
		
		/// <summary>
		/// Write the config to a file
		/// </summary>
		/// <param name="filename">The file to write to</param>
		/// <param name="lst">The ConfigList to save</param>
		public static void SaveConfig(string filename, ConfigList lst)
		{
			SaveConfig(filename, lst, new GeneralConfig());
		}
		
		/// <summary>
		/// Get the installed application location
		/// </summary>
		/// <param name="app">The application name</param>
		/// <returns>The location or null</returns>
		public static string GetInstalledLocation(string app)
		{
			ConfigList lst = XConf.LoadConfig("#software\\" + app + ".xbt");
			
			if (lst == null)
				return null;
			
			return lst["Location"];
		}
		
		/// <summary>
		/// XConf RelativeTo function
		/// </summary>
		/// <param name="location"></param>
		/// <returns></returns>
		public static string RelativeTo(string location)
		{
			return xsconf.RelativeTo(location);
		}
		
		/// <summary>
		/// Set the installed application location
		/// </summary>
		/// <param name="app">The application name</param>
		/// <param name="val">The new location</param>
		public static void SetInstalledLocation(string app, string val)
		{
			ConfigList lst = XConf.LoadConfig("#software\\" + app + ".xbt");
			
			if (lst == null)
				lst = new ConfigList();
			
			lst["Location"] = val;
			
			XConf.SaveConfig("#software\\" + app + ".xbt", lst);
		}
		
		/// <summary>
		/// The installed location for an application
		/// </summary>
		public static PropInstalled InstalledLocation
		{
			get
			{
				return new PropInstalled();
			}
		}
			
		/// <summary>
		/// AppInfo operator
		/// </summary>
		public class PropInstalled
		{
			/// <summary>
			/// Get/SetAppInfo operator
			/// </summary>
			public string this[string app]
			{
				get
				{
					return GetInstalledLocation(app);
				}
				set
				{
					SetInstalledLocation(app, value);
				}
			}
		}
	}
}
